﻿
namespace n_SOblect
{
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using n_HardModule;
using n_SimulateObj;
using n_SG;
using n_RA;
using n_SimPanel;
using n_Sprite;

public abstract class SObject
{
	public int Index;
	public HardModule Owner;
	
	public SObject O_Pre;
	public SObject O_Next;
	
	public float ForceX;
	public float ForceY;
	
	public float v_Z;
	public float Z {
		get {
			return v_Z;
		}
		set {
			v_Z = value;
			try{
			RefreshZ();
			}catch(Exception e){
				SimPanel.DebugMes += e.ToString();
			}
		}
	}
	
	public const int Addr_Systid = 0x0b;
	
	public const int Addr_Event = 0x0e;
	public int Event;
	
	public const int Addr_EventIndex = 0x0f;
	
	//方向角
	float v_imgAngle;
	public float imgAngle {
		get {
			return v_imgAngle;
		}
		set {
			v_imgAngle = value;
			RefreshLoc();
		}
	}
	
	public bool test;
	protected int NotHitIndex;
	
	
	public bool IgnXY;
	
	bool ttXNeedRefresh;
	float ttmyX;
	
	//ImgAngle旋转后的点
	protected float AX1, AY1;
	protected float AX2, AY2;
	protected float AX3, AY3;
	protected float AX4, AY4;
	
	//Angle旋转后的点
	protected float BX1, BY1;
	protected float BX2, BY2;
	protected float BX3, BY3;
	protected float BX4, BY4;
	
	//最小外接矩形
	public float rX, rY;
	public float rWidth, rHeight;
	protected int HitType;
	
	protected float v_myX;
	
	protected bool XExistHit;
	protected bool YExistHit;
	
	public float myX {
		get {
			return v_myX;
			
		}
		set {
			float t = v_myX;
			v_myX = value;
			
			if( IgnoreHit || IgnXY ) {
				XExistHit = false;
				
				RefreshX( v_myX - t );
				
				return;
			}
			SObject tar = null;
			if( HitBack() ) {
				Event |= 0x01;
				if( value < t ) {
					Event |= 0x08;
				}
				else {
					Event |= 0x10;
				}
				v_myX = t;
				ForceX = 0;
				XExistHit = true;
			}
			else if( (tar = HitSprite()) != null ) {
				Event |= 0x20;
				tar.Event |= 0x20;
				tar.test = true;
				test = true;
				if( value < t ) {
					Event |= 0x0100;
				}
				else {
					Event |= 0x0200;
				}
				v_myX = t;
				ForceX = 0;
				XExistHit = true;
			}
			else {
				XExistHit = false;
				
				RefreshX( v_myX - t );
				
			}
		}
	}
	
	public float MidX {
		get {
			return myX;
		}
		set {
			if( !n_SimPanel.SimPanel.Drawing ) {
				
				lock( SimPanel.isDrawing ) {
				myX = value;
				}
				ttXNeedRefresh = false;
			}
			else {
				ttmyX = value;
				ttXNeedRefresh = true;
			}
		}
	}
	public float SX {
		set {
			if( !n_SimPanel.SimPanel.Drawing ) {
				
				lock( SimPanel.isDrawing ) {
				myX = value + this.Width / 2 - RolX;
				}
				ttXNeedRefresh = false;
			}
			else {
				ttmyX = value + this.Width / 2 - RolX;
				ttXNeedRefresh = true;
			}
		}
		get {
			return myX - this.Width / 2 + RolX;
		}
	}
	
	
	float v_RolX;
	public float RolX {
		get {
			return v_RolX;
		}
		set {
			v_RolX = value;
			RefreshLoc();
		}
	}
	
	float v_RolY;
	public float RolY {
		get {
			return v_RolY;
		}
		set {
			v_RolY = value;
			RefreshLoc();
		}
	}
	
	
	bool ttYNeedRefresh;
	float ttmyY;
	protected float v_myY;
	
	public float myY {
		get {
			return v_myY;
		}
		set {
			float t = v_myY;
			v_myY = value;
			
			if( IgnoreHit || IgnXY ) {
				YExistHit = false;
				
				RefreshY( v_myY - t );
				
				return;
			}
			SObject tar = null;
			if( HitBack() ) {
				Event |= 0x01;
				if( value < t ) {
					Event |= 0x02;
				}
				else {
					Event |= 0x04;
				}
				v_myY = t;
				ForceY = 0;
				YExistHit = true;
			}
			else if( (tar = HitSprite()) != null ) {
				Event |= 0x20;
				tar.Event |= 0x20;
				tar.test = true;
				test = true;
				if( value < t ) {
					Event |= 0x40;
				}
				else {
					Event |= 0x80;
				}
				v_myY = t;
				ForceY = 0;
				YExistHit = true;
			}
			else {
				YExistHit = false;
				
				RefreshY( v_myY - t );
				
			}
		}
	}
	
	
	public bool EnableHit;
	
	public float MidY {
		get {
			return myY;
		}
		set {
			if( !n_SimPanel.SimPanel.Drawing ) {
				
				lock( SimPanel.isDrawing ) {
				myY = value;
				}
				ttYNeedRefresh = false;
			}
			else {
				ttmyY = value;
				ttYNeedRefresh = true;
			}
		}
	}
	public float SY {
		set {
			if( !n_SimPanel.SimPanel.Drawing ) {
				
				lock( SimPanel.isDrawing ) {
				myY = value + this.Height / 2 - RolY;
				}
				ttYNeedRefresh = false;
			}
			else {
				ttmyY = value + this.Height / 2 - RolY;
				ttYNeedRefresh = true;
			}
		}
		get {
			return myY - this.Height / 2 + RolY;
		}
	}
	
	bool ttANeedRefresh;
	float ttv_angle = 0;
	float v_angle;
	public float Angle {
		set {
			//if( !n_SimPanel.SimPanel.Drawing ) {
				
				float t = v_angle;
				
				v_angle = value;
				
				SObject tar = null;
				if( HitBack() ) {
					Event |= 0x01;
					v_angle = t;
				}
				else if( (tar = HitSprite()) != null ) {
					Event |= 0x20;
					tar.Event |= 0x20;
					
					tar.test = true;
					test = true;
					
					v_angle = t;
				}
				else {
					//ttANeedRefresh = false;
					
					RefreshLoc();
				}
			//}
			//else {
			//	ttv_angle = value;
			//	ttANeedRefresh = true;
			//}
		}
		get {
			return v_angle;
		}
	}
	
	
	float v_Width;
	public float Width {
		get {
			return v_Width;
		}
		set {
			v_Width = value;
			RefreshLoc();
		}
	}
	public float v_Height;
	public float Height {
		get {
			return v_Height;
		}
		set {
			v_Height = value;
			RefreshLoc();
		}
	}
	
	
	public float Last_mX;
	public float Last_mY;
	
	protected bool isMouseOn;
	public bool isMousePress;
	
	protected bool isRolOn;
	protected bool isRolPress;
	
	protected bool isRolMoveOn;
	protected bool isRolMovePress;
	
	protected bool isImgRolOn;
	protected bool isImgRolPress;
	
	protected bool MouseNear;
	
	public bool Selected;
	
	protected const float RolWidth = 20f;
	
	protected static Pen SelectPen;
	
	public bool NotDraw;
	
	public bool IgnoreHit;
	
	//是否为循迹传感器
	public bool isXunJi;
	
	//马达参数设置
	//是否为马达
	public bool isMotor;
	
	public bool SwapPin;
	public int StartPower;
	public int SpeedDown;
	public int Inertia;
	
	//是否隐藏
	public bool Visible;
	
	public bool isHit;
	public bool ByCopy;
	
	public bool EnableRolXY;
	public bool EnableSize;
	public bool EnableImgAngle;
	public bool EnableAngle;
	
	//初始化
	public static void SOblectInit()
	{
		SelectPen = new Pen( Color.OrangeRed, 3 );
	}
	
	//构造函数
	public SObject( HardModule o, int idx )
	{
		Owner = o;
		if( Owner != null ) {
			Owner.TargetSObject = this;
		}
		
		Index = idx;
		
		O_Pre = null;
		O_Next = null;
		
		ForceX = 0;
		ForceY = 0;
		
		RolX = 0;
		RolY = 0;
		
		HitType = 0;
		IgnXY = false;
		ByCopy = false;
		
		IgnoreHit = false;
		
		SX = 0;
		SY = 0;
		Width = 100;
		Height = 100;
		
		EnableHit = false;
		
		Event = 0;
		
		Visible = true;
		
		Angle = 0;
		imgAngle = 0;
		
		isHit = false;
		test = false;
		ttXNeedRefresh = false;
		ttYNeedRefresh = false;
		ttANeedRefresh = false;
		
		isMousePress = false;
		isMouseOn = false;
		isRolOn = false;
		MouseNear = false;
		
		isImgRolPress = false;
		isImgRolOn = false;
		
		Selected = false;
		
		
		SwapPin = false;
		StartPower = 5;
		SpeedDown = 50;
		Inertia = 50;
		
		HideMS();
	}
	
	//隐藏调节标志
	public void HideMS()
	{
		EnableRolXY = false;
		EnableSize = false;
		EnableImgAngle = false;
		EnableAngle = false;
	}
	
	//复位角色
	public void Reset()
	{
		Event = 0;
		IgnXY = true;
	}
	
	//复位仿真参数
	public abstract void ResetSimVar();
	
	//运行一步
	public abstract void RunStep( Bitmap Back, float DotNumber, float ix, float iy );
	
	//==================================================================================
	
	//判断是否和其他角色发生碰撞
	public SObject HitSprite()
	{
		if( !EnableHit ) {
			return null;
		}
		if( !ByCopy ) {
			return null;
		}
		if( SimPanel.O_Start == null ) {
			return null;
		}
		SObject t = SimPanel.O_Start.O_Next;
		while( t != SimPanel.O_End && t != null && this.Owner != null ) {
			
			if( t.Owner == this.Owner || t.IgnoreHit ) {
				t = t.O_Next;
				continue;
			}
			if( !t.ByCopy ) {
				t = t.O_Next;
				continue;
			}
			if( t is n_Sprite.Sprite && t != this && t.NotHitIndex != this.Owner.Index && this.NotHitIndex != t.Owner.Index ) {
				
				if( Math.Abs( t.Z - this.Z ) > 1 ) {
					continue;
				}
				HitType = 0;
				if( HitSprite1( this, t ) ) {
					return t;
				}
				if( HitSprite1( t, this ) ) {
					return t;
				}
			}
			t = t.O_Next;
		}
		return null;
	}
	
	//判断一个角色是否碰撞到另一个角色
	bool HitSprite1( SObject o, SObject t )
	{
		RectangleF rf1 = new RectangleF( t.rX, t.rY, t.rWidth, t.rHeight );
		if( !rf1.Contains( o.rX, o.rY ) &&
		    !rf1.Contains( o.rX + o.rWidth, o.rY ) &&
		    !rf1.Contains( o.rX, o.rY + o.rHeight ) &&
		    !rf1.Contains( o.rX + o.rWidth, o.rY + o.rHeight ) ) {
			return false;
		}
		HitType = 1;
		float xx, yy;
		RectangleF rf0 = new RectangleF( t.SX, t.SY, t.Width, t.Height );
		
		RolTrans( o, t, o.SX, o.SY, out xx, out yy );
		if( rf0.Contains( xx, yy ) ) {
			return true;
		}
		RolTrans( o, t, o.SX + o.Width, o.SY, out xx, out yy );
		if( rf0.Contains( xx, yy ) ) {
			return true;
		}
		RolTrans( o, t, o.SX, o.SY + o.Height, out xx, out yy );
		if( rf0.Contains( xx, yy ) ) {
			return true;
		}
		RolTrans( o, t, o.SX + o.Width, o.SY + o.Height, out xx, out yy );
		if( rf0.Contains( xx, yy ) ) {
			return true;
		}
		return false;
	}
	
	//判断一个角色是否碰撞到另一个角色(旧版)
	bool HitSprite0( SObject o, SObject t )
	{
		RectangleF rf1 = new RectangleF( t.rX, t.rY, t.rWidth, t.rHeight );
		if( !rf1.Contains( o.rX, o.rY ) &&
		    !rf1.Contains( o.rX + o.rWidth, o.rY ) &&
		    !rf1.Contains( o.rX, o.rY + o.rHeight ) &&
		    !rf1.Contains( o.rX + o.rWidth, o.rY + o.rHeight ) ) {
			return false;
		}
		HitType = 1;
		float xx, yy;
		RectangleF rf0 = new RectangleF( t.SX, t.SY, t.Width, t.Height );
		
		RolTrans1( t, o.BX1, o.BY1, out xx, out yy );
		if( rf0.Contains( xx, yy ) ) {
			return true;
		}
		RolTrans1( t, o.BX2, o.BY2, out xx, out yy );
		if( rf0.Contains( xx, yy ) ) {
			return true;
		}
		RolTrans1( t, o.BX3, o.BY3, out xx, out yy );
		if( rf0.Contains( xx, yy ) ) {
			return true;
		}
		RolTrans1( t, o.BX4, o.BY4, out xx, out yy );
		if( rf0.Contains( xx, yy ) ) {
			return true;
		}
		return false;
	}
	
	//判断是否和背景发生碰撞
	public bool HitBack()
	{
		if( !EnableHit ) {
			return false;
		}
		if( !ByCopy ) {
			return false;
		}
		if( HitBackBit( SX + Width/2, SY ) ) {
			return true;
		}
		if( HitBackBit( SX + Width/2, SY + Height ) ) {
			return true;
		}
		if( HitBackBit( SX, SY + Height/2 ) ) {
			return true;
		}
		if( HitBackBit( SX + Width, SY + Height/2 ) ) {
			return true;
		}
		if( HitBackBit( SX, SY ) ) {
			return true;
		}
		if( HitBackBit( SX, SY + Height ) ) {
			return true;
		}
		if( HitBackBit( SX + Width, SY )) {
			return true;
		}
		if( HitBackBit( SX + Width, SY + Height ) ) {
			return true;
		}
		return false;
	}
	
	bool HitBackBit( float nx, float ny )
	{
		float x = 0;
		float y = 0;
		RA.GetRolXY( out x, out y, nx - (SX + Width/2), ny - (SY + Height/2), imgAngle );
		x += SX + Width/2;
		y += SY + Height/2;
		
		
		RA.GetRolXY( out x, out y, x - MidX, y - MidY, Angle );
		x += MidX;
		y += MidY;
		
		
		int xx = (int)((x - n_SimPanel.SimPanel.ImgX + n_SimPanel.SimPanel.MapDotNumber/2) / n_SimPanel.SimPanel.MapDotNumber);
		int yy = (int)((y - n_SimPanel.SimPanel.ImgY + n_SimPanel.SimPanel.MapDotNumber/2) / n_SimPanel.SimPanel.MapDotNumber);
		
		lock( n_SimPanel.SimPanel.Back ) {
			if( xx > 0 && xx < n_SimPanel.SimPanel.Back.Width && yy > 0 && yy < n_SimPanel.SimPanel.Back.Height ) {
				
				Color c = n_SimPanel.SimPanel.Back.GetPixel( xx, yy );
				if( c.A != 0 && (c.R + c.G + c.B) / 3 < 200 ) {
					isHit = true;
					return true;
				}
				c = n_SimPanel.SimPanel.Back.GetPixel( xx, yy );
			}
			isHit = false;
			return false;
		}
	}
	
	//==================================================================================
	
	//更新当前模块的Z轴排序链表
	public void RefreshZ()
	{
		if( this == SimPanel.O_Start ||
		    this == SimPanel.O_End ||
		    this.O_Pre == null ||
		    this.O_Next == null ||
		    SimPanel.O_Start == null ||
		    SimPanel.O_End == null ) {
			return;
		}
		
		SObject pre = O_Pre;
		SObject next = O_Next;
		
		pre.O_Next = next;
		next.O_Pre = pre;
		
		if( pre != SimPanel.O_Start && pre.Z > Z ) {
			SObject t = pre;
			while( t != SimPanel.O_Start && t.Z > Z ) {
				t = t.O_Pre;
			}
			SObject tt = t.O_Next;
			
			t.O_Next = this;
			this.O_Pre = t;
			tt.O_Pre = this;
			this.O_Next = tt;
			return;
		}
		else {
			int x = 0;
			SObject t = next;
			while( t != SimPanel.O_End && t.Z < Z ) {
				t = t.O_Next;
				x++;
			}
			SObject tt = t.O_Pre;
			
			t.O_Pre = this;
			this.O_Next = t;
			tt.O_Next = this;
			this.O_Pre = tt;
			return;
		}
	}
	
	//==================================================================================
	
	//绘制
	public abstract void Draw( Graphics g );
	
	//判断是否需要重新刷新
	public bool NeedRefresh()
	{
		if( ttXNeedRefresh ) {
			myX = ttmyX;
		}
		if( ttYNeedRefresh ) {
			myY = ttmyY;
		}
		if( ttANeedRefresh ) {
			v_angle = ttv_angle;
		}
		
		if( !EnableHit ) {
			EnableHit = true;
		}
		
		if( ttXNeedRefresh || ttYNeedRefresh || ttANeedRefresh ) {
			ttXNeedRefresh = false;
			ttYNeedRefresh = false;
			ttANeedRefresh = false;
			return true;
		}
		return false;
	}
	
	//鼠标按下时
	public abstract bool LeftMouseDown( float eX, float eY );
	
	//鼠标松开时
	public abstract void LeftMouseUp( float eX, float eY );
	
	//鼠标移动时
	public abstract bool LeftMouseMove( float eX, float eY, bool MoveAll );
	
	//判断鼠标是否在当前组件上
	protected void MouseIsInside( float mX, float mY )
	{
		isRolOn = false;
		float w = (Width+Height) / 4;
		if( mX >= MidX + w - RolWidth && mX <= MidX + w && mY >= MidY - RolWidth/2 && mY <= MidY + RolWidth/2 ) {
			isRolOn = EnableAngle;
		}
	}
	
	//判断鼠标是否在当前组件上
	protected void MouseIsInsideRol( float mX, float mY )
	{
		//判断是否在组件上
		isMouseOn = false;
		if( mX >= SX && mX <= SX + Width && mY >= SY && mY <= SY + Height ) {
			isMouseOn = true;
		}
		
		int NearL = 20;
		MouseNear = false;
		if( mX >= SX - NearL && mX <= SX + Width + NearL && mY >= SY - Height - NearL && mY <= SY + Height + NearL ) {
			MouseNear = true;
		}
		
		float w = Width;
		if( w > Height ) {
			w = Height;
		}
		//判断是否在图片移动中心点
		w /= 8;
		isRolMoveOn = false;
		if( mX >= SX + Width/2 - w && mX <= SX + Width/2 + w && mY >=  SY + Height/2 - w && mY <= SY + Height/2 + w ) {
			isRolMoveOn = EnableRolXY;
		}
		//判断是否在图片旋转点
		float rw = w / 2;
		isImgRolOn = false;
		if( mX >= SX + Width/2 - rw && mX <= SX + Width/2 + rw && mY >=  SY && mY <= SY + rw * 2 ) {
			isImgRolOn = EnableImgAngle;
		}
	}
	
	//屏幕到世界坐标变换
	protected void GetWorldTrans( float mX, float mY, out float outx, out float outy )
	{
		double ox, oy, R, I, dx, dy;
		
		/*
		ox = mX - SX + Width/2;
		oy = mY - SY + Height/2;
		R = Math.Cos( imgAngle * Math.PI/180 );
		I = Math.Sin( imgAngle * Math.PI/180 );
		dx = ox*R - oy*I;
		dy = ox*I + oy*R;
		mX = SX + Width/2 + (float)dx;
		mY = SY + Height/2 + (float)dy;
		*/
		
		float oox = mX - SimPanel.CamMidX;
		float ooy = mY - SimPanel.CamMidY;
		mX = SimPanel.CamMidX + oox * GetZTrans();
		mY = SimPanel.CamMidY + ooy * GetZTrans();
		
		ox = mX - MidX;
		oy = mY - MidY;
		R = Math.Cos( Angle * Math.PI/180 );
		I = Math.Sin( Angle * Math.PI/180 );
		dx = ox*R - oy*I;
		dy = ox*I + oy*R;
		mX = MidX + (float)dx;
		mY = MidY + (float)dy;
		
		
		outx = mX;
		outy = mY;
	}
	
	//屏幕到世界坐标变换
	protected void GetWorldTransEage( float mX, float mY, out float outx, out float outy )
	{
		float oox = mX - SimPanel.CamMidX;
		float ooy = mY - SimPanel.CamMidY;
		mX = SimPanel.CamMidX + oox * GetZTrans();
		mY = SimPanel.CamMidY + ooy * GetZTrans();
		
		outx = mX;
		outy = mY;
	}
	
	//偏移角变换
	protected void ImgTrans( float mX, float mY, out float outx, out float outy, bool f )
	{
		double ox, oy, R, I, dx, dy;
		
		ox = mX - (SX + Width/2);
		oy = mY - (SY + Height/2);
		
		if( f ) {
			R = Math.Cos( imgAngle * Math.PI/180 );
			I = Math.Sin( imgAngle * Math.PI/180 );
		}
		else {
			R = Math.Cos( -imgAngle * Math.PI/180 );
			I = Math.Sin( -imgAngle * Math.PI/180 );
		}
		
		dx = ox*R - oy*I;
		dy = ox*I + oy*R;
		mX = SX + Width/2 + (float)dx;
		mY = SY + Height/2 + (float)dy;
		
		outx = mX;
		outy = mY;
	}
	
	//==========================================================================
	
	public bool NeedRedraw;
	
	//更新碰撞X
	void RefreshX( float of )
	{
		NeedRedraw = true;
		
		rX += of;
		BX1 += of;
		BX2 += of;
		BX3 += of;
		BX4 += of;
	}
	
	//更新碰撞Y
	void RefreshY( float of )
	{
		NeedRedraw = true;
		
		rY += of;
		BY1 += of;
		BY2 += of;
		BY3 += of;
		BY4 += of;
	}
	
	//刷新外边框
	void RefreshLoc()
	{
		LocTrans( SX, SY, out BX1, out BY1 );
		LocTrans( SX + Width, SY, out BX2, out BY2 );
		LocTrans( SX, SY + Height, out BX3, out BY3 );
		LocTrans( SX + Width, SY + Height, out BX4, out BY4 );
		
		float rXX = BX1;
		rX = BX1;
		if( rX > BX2 ) {
			rX = BX2;
		}
		if( rXX < BX2 ) {
			rXX = BX2;
		}
		if( rX > BX3 ) {
			rX = BX3;
		}
		if( rXX < BX3 ) {
			rXX = BX3;
		}
		if( rX > BX4 ) {
			rX = BX4;
		}
		if( rXX < BX4 ) {
			rXX = BX4;
		}
		float rYY = BY1;
		rY = BY1;
		if( rY > BY2 ) {
			rY = BY2;
		}
		if( rYY < BY2 ) {
			rYY = BY2;
		}
		if( rY > BY3 ) {
			rY = BY3;
		}
		if( rYY < BY3 ) {
			rYY = BY3;
		}
		if( rY > BY4 ) {
			rY = BY4;
		}
		if( rYY < BY4 ) {
			rYY = BY4;
		}
		rWidth = rXX - rX;
		rHeight = rYY - rY;
	}
	
	//计算ImgAngle旋转后的点
	void LocTrans( float mX, float mY, out float outx, out float outy )
	{
		IRolTrans( this, mX, mY, out outx, out outy, false );
		ARolTrans( this, outx, outy, out outx, out outy, false );
	}
	
	//旋转角变换, 仅用于角色碰撞检测关键点变换
	void RolTrans( SObject o, SObject t, float mX, float mY, out float outx, out float outy )
	{
		IRolTrans( o, mX, mY, out outx, out outy, false );
		ARolTrans( o, outx, outy, out outx, out outy, false );
		
		ARolTrans( t, outx, outy, out outx, out outy, true );
		IRolTrans( t, outx, outy, out outx, out outy, true );
	}
	
	//旋转角变换, 仅用于角色碰撞检测关键点变换
	void RolTrans1( SObject t, float mX, float mY, out float outx, out float outy )
	{
		ARolTrans( t, mX, mY, out outx, out outy, true );
		IRolTrans( t, outx, outy, out outx, out outy, true );
	}
	
	void ARolTrans( SObject o, float mX, float mY, out float outx, out float outy, bool f )
	{
		double ox, oy, R, I, dx, dy;
		
		ox = mX - o.MidX;
		oy = mY - o.MidY;
		
		if( f ) {
			R = Math.Cos( o.Angle * Math.PI/180 );
			I = Math.Sin( o.Angle * Math.PI/180 );
		}
		else {
			R = Math.Cos( -o.Angle * Math.PI/180 );
			I = Math.Sin( -o.Angle * Math.PI/180 );
		}
		
		dx = ox*R - oy*I;
		dy = ox*I + oy*R;
		mX = o.MidX + (float)dx;
		mY = o.MidY + (float)dy;
		
		outx = mX;
		outy = mY;
	}
	
	void IRolTrans( SObject o, float mX, float mY, out float outx, out float outy, bool f )
	{
		double ox, oy, R, I, dx, dy;
		
		ox = mX - (o.SX + o.Width/2);
		oy = mY - (o.SY + o.Height/2);
		
		if( f ) {
			R = Math.Cos( o.imgAngle * Math.PI/180 );
			I = Math.Sin( o.imgAngle * Math.PI/180 );
		}
		else {
			R = Math.Cos( -o.imgAngle * Math.PI/180 );
			I = Math.Sin( -o.imgAngle * Math.PI/180 );
		}
		
		dx = ox*R - oy*I;
		dy = ox*I + oy*R;
		mX = o.SX + o.Width/2 + (float)dx;
		mY = o.SY + o.Height/2 + (float)dy;
		
		outx = mX;
		outy = mY;
	}
	
	public RectangleF rrr;
	
	//获取刷新边框
	public RectangleF GetRefreshRect()
	{
		float xx1, yy1;
		GetScreenTransAAA( rX, rY, out xx1, out yy1 );
		float xx4, yy4;
		GetScreenTransAAA( rX + rWidth, rY + rHeight, out xx4, out yy4 );
		
		rrr = new RectangleF( xx1, yy1, xx4 - xx1, yy4 - yy1 );
		return rrr;
	}
	
	//世界到屏幕坐标变换
	void GetScreenTransAAA( float wX, float wY, out float outx, out float outy )
	{
		float oox = wX - SimPanel.CamMidX;
		float ooy = wY - SimPanel.CamMidY;
		
		outx = SimPanel.CamWidth/2 + oox * GetFZTrans();
		outy = SimPanel.CamHeight/2 + ooy * GetFZTrans();
	}
	
	//==========================================================================
	
	//世界到屏幕坐标变换
	protected void GetScreenTrans( float wX, float wY, out float outx, out float outy )
	{
		//wX += RolX;
		//wY += RolY;
		
		float ox = wX - MidX;
		float oy = wY - MidY;
		double R = Math.Cos( -Angle * Math.PI/180 );
		double I = Math.Sin( -Angle * Math.PI/180 );
		double dx = ox*R - oy*I;
		double dy = ox*I + oy*R;
		outx = MidX + (float)dx;
		outy = MidY + (float)dy;
		
		float oox = outx - SimPanel.CamMidX;
		float ooy = outy - SimPanel.CamMidY;
		
		outx = SimPanel.CamMidX + oox * GetFZTrans();
		outy = SimPanel.CamMidY + ooy * GetFZTrans();
	}
	
	//计算X的透视变换
	protected float GetXT( float x )
	{
		return ( x - SimPanel.CamMidX ) / GetZTrans() + SimPanel.CamMidX;
	}
	
	//计算Y的透视变换
	protected float GetYT( float y )
	{
		return ( y - SimPanel.CamMidY ) / GetZTrans() + SimPanel.CamMidY;
	}
	
	//计算透视变换
	protected float GetZTrans()
	{
		return (Z - SimPanel.CamZ) / SimPanel.StdDis;
	}
	
	//计算反透视变换
	protected float GetFZTrans()
	{
		float oz = (Z - SimPanel.CamZ);
		if( Math.Abs( oz ) < 1 ) {
			oz = 1;
		}
		return SimPanel.StdDis / oz;
	}
}
}


